import 'dart:math' as math;

import 'package:flutter/material.dart';

import '../base/christmas_light_style.dart';

/// RGB 选择器
class RGBSlider extends StatelessWidget {
  final Color color;
  final ValueChanged<Color>? onChanged;
  final ValueChanged<Color>? onChangeEnd;
  final double? spacing;

  const RGBSlider({
    Key? key,
    required this.color,
    this.onChanged,
    this.onChangeEnd,
    this.spacing
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    late double _hue = HSVColor.fromColor(color).hue;
    late double _saturation = HSVColor.fromColor(color).saturation;
    return Column(
      children: [
        ColorSaturationSlider(
          hue: _hue,
          saturation: _saturation,
          onChanged: (saturation) {
            final hsv = HSVColor.fromAHSV(1.0, _hue, saturation, 1.0);
            onChanged?.call(hsv.toColor());
          },
          onChangeEnd: (saturation) {
            final hsv = HSVColor.fromAHSV(1.0, _hue, saturation, 1.0);
            onChangeEnd?.call(hsv.toColor());
          },
        ),
        SizedBox(height: spacing??10),
        ColorTweenSlider(
          hue: _hue,
          onChanged: (hue) {
            final hsv = HSVColor.fromAHSV(1.0, hue, _saturation, 1.0);
            onChanged?.call(hsv.toColor());
          },
          onChangeEnd: (hue) {
            final hsv = HSVColor.fromAHSV(1.0, hue, _saturation, 1.0);
            onChangeEnd?.call(hsv.toColor());
          },
        ),
      ],
    );
  }
}

/// 颜色饱和度选择器
class ColorSaturationSlider extends StatefulWidget {
  final double hue;
  final double saturation;
  final ValueChanged<double>? onChanged;
  final ValueChanged<double>? onChangeEnd;

  const ColorSaturationSlider({
    Key? key,
    required this.hue,
    required this.saturation,
    this.onChanged,
    this.onChangeEnd,
  })  : assert(hue >= 0.0 && hue <= 360.0),
        assert(saturation >= 0.0 && saturation <= 1.0),
        super(key: key);

  @override
  State<ColorSaturationSlider> createState() => _ColorSaturationSliderState();
}

class _ColorSaturationSliderState extends State<ColorSaturationSlider> {
  late double _hue = widget.hue;
  late double _saturation = widget.saturation;
  late List<Color> _colors = List.generate(100, (index) {
    double _s = 1 - (index / 100);
    return HSVColor.fromAHSV(1.0, _hue, _s.clamp(0.0, 1.0), 1.0).toColor();
  });

  @override
  void didUpdateWidget(covariant ColorSaturationSlider oldWidget) {
    setState(() {
      _hue = widget.hue;
      _saturation = widget.saturation;
      _colors = List.generate(100, (index) {
        double _s = 1 - (index / 100);
        return HSVColor.fromAHSV(1.0, _hue, _s.clamp(0.0, 1.0), 1.0).toColor();
      });
    });
    super.didUpdateWidget(oldWidget);
  }

  @override
  Widget build(BuildContext context) {
    Color _color = HSVColor.fromAHSV(1.0, _hue, _saturation, 1.0).toColor();
    return SizedBox(
      width: double.infinity,
      height: 50.0,
      child: Stack(
        alignment: Alignment.center,
        children: [
          Positioned(
            left: 16.0,
            right: 16.0,
            child: Container(
              width: double.infinity,
              height: 5.0,
              decoration: BoxDecoration(
                borderRadius: BorderRadius.circular(15),
                gradient: LinearGradient(colors: _colors),
              ),
            ),
          ),
          SliderTheme(
            data: SliderTheme.of(context).copyWith(
              thumbColor: _color,
              overlayShape: RoundSliderOverlayShape(overlayRadius: 12.0),
              thumbShape: MyThumbShape(),
              disabledActiveTrackColor: Colors.transparent,
              activeTrackColor: Colors.transparent,
              inactiveTrackColor: Colors.transparent,
              overlayColor: _color.withOpacity(0.1),
            ),
            child: Slider(
              min: 0.0,
              max: 1.0,
              value: (1 - _saturation).clamp(0.0, 1.0),
              onChanged: (saturation) {
                setState(() => _saturation = (1 - saturation).clamp(0.0, 1.0));
                widget.onChanged?.call(_saturation);
              },
              onChangeEnd: (saturation) {
                setState(() => _saturation = (1 - saturation).clamp(0.0, 1.0));
                widget.onChangeEnd?.call(_saturation);
              },
            ),
          )
        ],
      ),
    );
  }
}

/// 颜色区间选择器
class ColorTweenSlider extends StatefulWidget {
  final double hue;
  final ValueChanged<double>? onChanged;
  final ValueChanged<double>? onChangeEnd;

  const ColorTweenSlider({
    Key? key,
    required this.hue,
    this.onChanged,
    this.onChangeEnd,
  }) : super(key: key);

  @override
  State<ColorTweenSlider> createState() => _ColorTweenSliderState();
}

class _ColorTweenSliderState extends State<ColorTweenSlider> {
  final List<Color> _colors = List.generate(360, (hue) {
    return HSVColor.fromAHSV(1.0, hue.toDouble(), 1.0, 1.0).toColor();
  });

  late Color _color = HSVColor.fromAHSV(1.0, widget.hue, 1.0, 1.0).toColor();

  @override
  Widget build(BuildContext context) {
    return SizedBox(
      width: double.infinity,
      height: 50.0,
      child: Stack(
        alignment: Alignment.center,
        children: [
          Positioned(
            left: 16.0,
            right: 16.0,
            child: Container(
              width: double.infinity,
              height: 5.0,
              decoration: BoxDecoration(
                borderRadius: BorderRadius.circular(15),
                gradient: LinearGradient(colors: _colors),
              ),
            ),
          ),
          SliderTheme(
            data: SliderTheme.of(context).copyWith(
              thumbColor: _color,
              thumbShape: MyThumbShape(),
              overlayShape: RoundSliderOverlayShape(overlayRadius: 12.0),
              disabledActiveTrackColor: Colors.transparent,
              activeTrackColor: Colors.transparent,
              inactiveTrackColor: Colors.transparent,
              overlayColor: _color.withOpacity(0.09),
            ),
            child: Slider(
              min: 0.0,
              max: 360.0,
              value: widget.hue,
              onChanged: (hue) {
                setState(() {
                  _color = HSVColor.fromAHSV(1.0, hue, 1.0, 1.0).toColor();
                });
                widget.onChanged?.call(hue);
              },
              onChangeEnd: (hue) {
                setState(() {
                  _color = HSVColor.fromAHSV(1.0, hue, 1.0, 1.0).toColor();
                });
                widget.onChangeEnd?.call(hue);
              },
            ),
          )
        ],
      ),
    );
  }
}

/// 对称进度条
class ChristmasLightSymmetrySlider extends StatefulWidget {
  final double value;

  // 最左端数值
  final int leftNum;

  // 最右端数值
  final int rightNum;
  final double trackHeight;
  final double height;
  final ValueChanged<double>? onChanged;
  final ValueChanged<double>? onChangeEnd;

  const ChristmasLightSymmetrySlider({
    Key? key,
    required this.value,
    this.trackHeight = 5,
    this.height = 36.0,
    this.leftNum = -100,
    this.rightNum = 100,
    this.onChanged,
    this.onChangeEnd,
  })  : assert(value >= leftNum && value <= rightNum),
        super(key: key);

  @override
  State<ChristmasLightSymmetrySlider> createState() =>
      _ChristmasLightSymmetrySliderState();
}

class _ChristmasLightSymmetrySliderState
    extends State<ChristmasLightSymmetrySlider> {
  late double _sliderValue = widget.value;
  bool manualChanged = false;

  @override
  void didUpdateWidget(covariant ChristmasLightSymmetrySlider oldWidget) {
    if (oldWidget.value != widget.value && !manualChanged) {
      setState(() {
        _sliderValue = widget.value;
      });
    }
    manualChanged = false;
    super.didUpdateWidget(oldWidget);
  }

  double _leftWidth(double maxWidth, double value) {
    if (value < 0) {
      int leftNum = widget.leftNum.abs();
      return (maxWidth / leftNum) * value.abs();
    }
    return maxWidth;
  }

  double _rightWidth(double maxWidth, double value) {
    if (value > 0) {
      int rightNum = widget.rightNum.abs();
      return (maxWidth / rightNum) * value.abs();
    }
    return maxWidth;
  }

  Color _leftColor(double value) {
    Color color = christmasLightStyle.progressBackgroundColor;
    if (value == 0) {
      color = christmasLightStyle.progressBackgroundColor;
    } else if (value < 0) {
      color = Colors.white;
    }
    return color;
  }

  Color _rightColor(double value) {
    Color color = christmasLightStyle.progressBackgroundColor;
    if (value == 0) {
      color = christmasLightStyle.progressBackgroundColor;
    } else if (value > 0) {
      color = Colors.white;
    }
    return color;
  }

  Widget _leftBox() {
    return Expanded(
      child: LayoutBuilder(
        builder: (_, constraints) {
          return Container(
            height: widget.trackHeight,
            color: christmasLightStyle.progressBackgroundColor,
            alignment: Alignment.centerRight,
            child: Container(
              height: widget.trackHeight,
              width: _leftWidth(constraints.maxWidth, _sliderValue),
              color: _leftColor(_sliderValue),
            ),
          );
        },
      ),
    );
  }

  Widget _rightBox() {
    return Expanded(
      child: LayoutBuilder(
        builder: (_, constraints) {
          return Container(
            height: widget.trackHeight,
            color: christmasLightStyle.progressBackgroundColor,
            alignment: Alignment.centerLeft,
            child: Container(
              height: widget.trackHeight,
              width: _rightWidth(constraints.maxWidth, _sliderValue),
              color: _rightColor(_sliderValue),
            ),
          );
        },
      ),
    );
  }

  @override
  Widget build(BuildContext context) {
    return SizedBox(
      height: widget.height,
      child: Stack(
        alignment: AlignmentDirectional.center,
        children: [
          Padding(
            padding: const EdgeInsets.symmetric(horizontal:12,vertical: 16),
            child: ClipRRect(
              borderRadius: BorderRadius.circular(5.0),
              child: Row(children: [_leftBox(), _rightBox()]),
            ),
          ),
          SliderTheme(
            data: SliderTheme.of(context).copyWith(
              thumbColor: Colors.black,
              thumbShape: MyThumbShape(),
              overlayShape: RoundSliderOverlayShape(overlayRadius: 12.0),
              disabledActiveTrackColor: Colors.transparent,
              activeTrackColor: Colors.transparent,
              inactiveTrackColor: Colors.transparent,
              overlayColor: Colors.white12,
            ),
            child: Slider(
              value: _sliderValue,
              min: widget.leftNum.toDouble(),
              max: widget.rightNum.toDouble(),
              // divisions: widget.leftNum.abs() + widget.rightNum.abs(),
              onChanged: (value) {
                manualChanged = true;
                setState(() => _sliderValue = value);
                widget.onChanged?.call(_sliderValue);
              },
              onChangeEnd: (value) {
                setState(() => _sliderValue = value);
                widget.onChangeEnd?.call(_sliderValue);
              },
            ),
          ),
        ],
      ),
    );
  }
}

/// 通用进度条
class ChristmasLightSlider extends StatelessWidget {
  final double value;
  final double min;
  final double max;
  final ValueChanged<double>? onChanged;
  final ValueChanged<double>? onChangeEnd;
  final double trackHeight;

  const ChristmasLightSlider(
      {Key? key,
      required this.value,
      this.min = 0,
      this.max = 100,
      this.onChanged,
      this.onChangeEnd,
      this.trackHeight = 4})
      : super(key: key);

  @override
  Widget build(BuildContext context) {
    return SliderTheme(
      data: SliderTheme.of(context).copyWith(
        thumbColor: Colors.black,
        thumbShape: MyThumbShape(),
        trackHeight: trackHeight,
        trackShape: MyTrackShape(),
        overlayShape: RoundSliderOverlayShape(overlayRadius: 12),
        activeTrackColor: Colors.white,
        inactiveTrackColor: christmasLightStyle.progressBackgroundColor,
        overlayColor: Colors.white12,
      ),
      child: Slider(
        min: min,
        max: max,
        value: value,
        onChanged: (value) => onChanged?.call(value),
        onChangeEnd: (value) => onChangeEnd?.call(value),
      ),
    );
  }
}

class MyTrackShape extends RoundedRectSliderTrackShape{
  @override
  void paint(PaintingContext context, Offset offset, {required RenderBox parentBox, required SliderThemeData sliderTheme, required Animation<double> enableAnimation, required TextDirection textDirection, required Offset thumbCenter, Offset? secondaryOffset, bool isDiscrete = false, bool isEnabled = false, double additionalActiveTrackHeight = 2}) {
    super.paint(context, offset,
        parentBox: parentBox,
        sliderTheme: sliderTheme,
        enableAnimation: enableAnimation,
        textDirection: textDirection,
        thumbCenter: thumbCenter,
        isDiscrete: isDiscrete,
        isEnabled: isEnabled,
        additionalActiveTrackHeight: 0);
  }
}

class MyThumbShape extends SliderComponentShape {
  const MyThumbShape({
    this.thumbStrokeColor = Colors.white,
    this.strokeWidth = 2.0,
    this.enabledThumbRadius = 10.0,
    this.disabledThumbRadius,
    this.elevation = 1.0,
    this.pressedElevation = 6.0,
  });

  final Color thumbStrokeColor;
  final double strokeWidth;
  final double enabledThumbRadius;
  final double? disabledThumbRadius;

  double get _disabledThumbRadius => disabledThumbRadius ?? enabledThumbRadius;
  final double elevation;
  final double pressedElevation;

  @override
  Size getPreferredSize(bool isEnabled, bool isDiscrete) {
    return Size.fromRadius(
      isEnabled == true ? enabledThumbRadius : _disabledThumbRadius,
    );
  }

  @override
  void paint(
    PaintingContext context,
    Offset center, {
    required Animation<double> activationAnimation,
    required Animation<double> enableAnimation,
    required bool isDiscrete,
    required TextPainter labelPainter,
    required RenderBox parentBox,
    required SliderThemeData sliderTheme,
    required TextDirection textDirection,
    required double value,
    required double textScaleFactor,
    required Size sizeWithOverflow,
  }) {
    assert(sliderTheme.disabledThumbColor != null);
    assert(sliderTheme.thumbColor != null);

    final Canvas canvas = context.canvas;

    final Tween<double> radiusTween = Tween<double>(
      begin: _disabledThumbRadius,
      end: enabledThumbRadius,
    );

    final ColorTween colorTween = ColorTween(
      begin: sliderTheme.disabledThumbColor,
      end: sliderTheme.thumbColor,
    );

    final Color color = colorTween.evaluate(enableAnimation)!;
    final double radius = radiusTween.evaluate(enableAnimation);

    final Tween<double> elevationTween = Tween<double>(
      begin: elevation,
      end: pressedElevation,
    );

    final double evaluatedElevation = elevationTween.evaluate(
      activationAnimation,
    );

    double width = 2 * radius;
    double height = 2 * radius;
    Rect rect = Rect.fromCenter(center: center, width: width, height: height);

    final Path path = Path()..addArc(rect, 0, math.pi * 2);
    canvas.drawShadow(path, Colors.black, evaluatedElevation, true);

    Paint p1 = Paint()
      ..color = thumbStrokeColor
      ..strokeWidth = strokeWidth;

    Paint p2 = Paint()..color = color;

    /// 外圈
    canvas.drawCircle(center, radius, p1);

    /// 内圈
    canvas.drawCircle(center, radius - strokeWidth, p2);
  }
}
